using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using Newtonsoft.Json;
using RevitCopilot.MCPServer.Models;

namespace RevitCopilot.MCPServer.Services;

// Socket通信服务类，用于与Revit插件服务端进行通信
public class SocketService
{
    private Socket? _clientSocket;
    private readonly string _serverIp;
    private readonly int _serverPort;
    private bool _isConnected;
    // 服务器IP地址，服务器端口，容器自动装配总是调用参数最多的构造函数
    public SocketService(string serverIp = "127.0.0.1", int serverPort = 8080)
    {
        _serverIp = serverIp;
        _serverPort = serverPort;
        _isConnected = false;
    }
    string logPath = @"log.txt";
    // 连接到Revit插件服务端ServerSocket(连接是否成功)
    public bool Connect()
    {
        try
        {
            if (_isConnected && _clientSocket != null)
            {
                return true;
            }
            _clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse(_serverIp), _serverPort);
            //Client是connect，Server是bind
            _clientSocket.Connect(serverEndPoint);
            _isConnected = _clientSocket.Connected;
            File.AppendAllText(logPath, $"连接Revit插件服务端ServerSocket成功");
            return _isConnected;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"连接Revit插件服务端ServerSocket失败: {ex.Message}");
            _isConnected = false;
            File.AppendAllText(logPath, $"连接Revit插件服务端ServerSocket成功");
            return false;
        }
    }
    // 发送Revit需要执行的方法名和参数到Revit插件服务端
    /// <summary>
    /// 生成唯一的请求ID
    /// </summary>
    /// <returns>唯一请求ID</returns>
    private string GenerateRequestId()
    {
        return DateTime.Now.Ticks.ToString() + new Random().Next(100000, 999999).ToString();
    }

    public bool SendRequest(string methodName, object parameters)
    {
        if (!_isConnected || _clientSocket == null)
        {
            if (!this.Connect())
            {
                return false;
            }
        }
        try
        {
            // 创建符合JSON-RPC 2.0规范的请求对象
            var request = new JsonRpcRequest
            {
                Method = methodName,
                Params = parameters,
                Id = GenerateRequestId()
            };
            // 序列化请求对象
            string jsonRequest = JsonConvert.SerializeObject(request);
            byte[] requestData = Encoding.UTF8.GetBytes(jsonRequest);
            // 发送数据长度
            byte[] lengthBytes = BitConverter.GetBytes(requestData.Length);
            _clientSocket.Send(lengthBytes);
            // 发送实际数据
            _clientSocket.Send(requestData);
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"向Revit发送执行方法请求失败: {ex.Message}");
            Disconnect();
            return false;
        }
    }
     //接收Revit插件服务端的响应，revit返回的方法执行后的数据
    public T? ReceiveResponse<T>()
    {
        if (!_isConnected || _clientSocket == null)
        {
            return default;
        }
        try
        {
            // 接收数据长度
            byte[] lengthBytes = new byte[4];
            _clientSocket.Receive(lengthBytes);
            int dataLength = BitConverter.ToInt32(lengthBytes, 0);
            // 接收实际数据
            byte[] responseData = new byte[dataLength];
            int receivedLength = 0;
            while (receivedLength < dataLength)
            {
                receivedLength += _clientSocket.Receive(responseData, receivedLength, dataLength - receivedLength, SocketFlags.None);
            }
            string jsonResponse = Encoding.UTF8.GetString(responseData);
            return JsonConvert.DeserializeObject<T>(jsonResponse);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"接收响应失败: {ex.Message}");
            Disconnect();
            return default;
        }
    }

    // McpTool调用完毕，断开与Revit插件服务端的连接，释放ClientSocket
    public void Disconnect()
    {
        if (_clientSocket != null)
        {
            try
            {
                if (_isConnected)
                {
                    _clientSocket.Shutdown(SocketShutdown.Both);
                }
                _clientSocket.Close();
                _clientSocket.Dispose();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"断开连接时发生错误: {ex.Message}");
            }
            finally
            {
                _clientSocket = null;
                _isConnected = false;
            }
        }
    }
}